﻿using System;
using System.IO;
using Infrastructure.CrossCutting.Converters;
using Infrastructure.CrossCutting.Messages;

namespace Infrastructure.CrossCutting.Arguments
{
    [AttributeUsage(AttributeTargets.Property)]
    public class ArgumentAttribute : Attribute
    {
        public string ShortName { get; set; }

        public string LongName { get; set; }

        public string Description { get; set; }

        public bool IsOptional { get; set; }

        public bool Found { get; set; }

        public bool NeedValue { get; set; }

        public object DefaultValue { get; set; }

        public object Value { get; set; }

        public Type ValueType { get; set; }

        public string Example { get; set; }

        public ArgumentAttribute()
        {
            
        }

        public ArgumentAttribute(string shortName, string longName, string description, bool isOptional = false, bool needValue = false, Type valueType = null, object defaultValue = null, string example = "")
        {
            Init(shortName, longName, description, isOptional, needValue, valueType, defaultValue, example);
        }

        public void Init(string shortName, string longName, string description, bool isOptional = false, bool needValue = false, Type valueType = null, object defaultValue = null, string example = "")
        {
            ShortName = shortName;
            LongName = longName;
            Description = description;
            IsOptional = isOptional;
            NeedValue = needValue;
            ValueType = valueType;
            DefaultValue = defaultValue;
            Example = example;
        }

        /// <summary>
        /// Build the usage for this argument.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string val = "";
            string startId = LongName;

            val += string.IsNullOrEmpty(Description) ? string.Empty : Description + ", ";
            val += IsOptional ? "Required" : "Optional";
            if (NeedValue)
            {
                val += ", NeedValue:" + ValueType.Name + ", ";
                val += DefaultValue != null ? ", default to : " + DefaultValue : string.Empty;
            }
            val = startId + val;
            return val;
        }

        internal BoolMessage Validate(string value)
        {
            if (!IsOptional && string.IsNullOrEmpty(value))
                return BoolMessage.False.SetMessage(string.Format("Required argument '{0}' : {1} is missing.", LongName, ValueType.FullName));

            if (IsOptional && string.IsNullOrEmpty(value))
                return BoolMessage.True;

            if (ValueType == typeof(FileInfo) && !File.Exists(value))
                return
                    BoolMessage.False.SetMessage(
                        string.Format("File '{0}' associated with argument '{1}' does not exist.", value, LongName));

            if (ValueType == typeof(DirectoryInfo) && !Directory.Exists(value))
                return
                    BoolMessage.False.SetMessage(
                        string.Format("Directory '{0}' associated with argument '{1}' does not exist.", value, LongName));

            if (!DataTypeConverter.CanConvertTo(ValueType, value))
                return
                    BoolMessage.False.SetMessage(
                        string.Format("Argument value of '{0}' for '{1}' does not match type {2}.",
                                      value, LongName, ValueType.FullName));

            return BoolMessage.True;

        }
    }
}
